package com.simon.train.business.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.simon.train.business.domain.DailyTrain;
import com.simon.train.business.domain.DailyTrainExample;
import com.simon.train.business.domain.Train;
import com.simon.train.business.dto.DailyTrainQueryDto;
import com.simon.train.business.dto.DailyTrainSaveDto;
import com.simon.train.business.mapper.DailyTrainMapper;
import com.simon.train.business.vo.DailyTrainQueryVO;
import com.simon.train.common.util.SnowUtil;
import com.simon.train.common.vo.PageVO;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Service
public class DailyTrainService {

    private static final Logger LOG = LoggerFactory.getLogger(DailyTrainService.class);

    @Resource
    private DailyTrainMapper dailyTrainMapper;

    @Resource
    private TrainService trainService;

    @Resource
    private DailyTrainStationService dailyTrainStationService;

    @Resource
    private DailyTrainCarriageService dailyTrainCarriageService;

    @Resource
    private DailyTrainSeatService dailyTrainSeatService;

    @Resource
    private DailyTrainTicketService dailyTrainTicketService;

    public void SaveDailyTrain(DailyTrainSaveDto dailyTrainSaveDto){
        DailyTrain dailyTrain = BeanUtil.copyProperties(dailyTrainSaveDto, DailyTrain.class);
        if (ObjectUtil.isNull(dailyTrain.getId())){
            //对于首次保存 也就是新增 需要对字段单独做处理
            dailyTrain.setId(SnowUtil.getSnowflakeNextId());
            DateTime time = DateTime.now();
            dailyTrain.setCreateTime(time);
            dailyTrain.setUpdateTime(time);
            dailyTrainMapper.insert(dailyTrain);
        } else {
            dailyTrain.setUpdateTime(DateTime.now());
            dailyTrainMapper.updateByPrimaryKey(dailyTrain);
        }

    }

    public PageVO<DailyTrainQueryVO> QueryDailyTrainList(DailyTrainQueryDto dailyTrainQueryDto){
        DailyTrainExample dailyTrainExample = new DailyTrainExample();
        dailyTrainExample.setOrderByClause("date desc, code asc");
        DailyTrainExample.Criteria criteria = dailyTrainExample.createCriteria();

        if(ObjectUtil.isNotNull(dailyTrainQueryDto.getDate())){
            criteria.andDateEqualTo(dailyTrainQueryDto.getDate());
        }

        if(ObjectUtil.isNotEmpty(dailyTrainQueryDto.getCode())){
            criteria.andCodeEqualTo(dailyTrainQueryDto.getCode());
        }

        LOG.info("当前请求的页码：{}", dailyTrainQueryDto.getPage());
        LOG.info("每页条数：{}", dailyTrainQueryDto.getPageSize());

        PageHelper.startPage(dailyTrainQueryDto.getPage(),dailyTrainQueryDto.getPageSize());
        List<DailyTrain> dailyTrainList = dailyTrainMapper.selectByExample(dailyTrainExample);

        PageInfo<DailyTrain> pageInfo = new PageInfo<>(dailyTrainList);
        LOG.info("总行数：{}", pageInfo.getTotal());
        LOG.info("总页数：{}", pageInfo.getPages());

        List<DailyTrainQueryVO> lists = BeanUtil.copyToList(dailyTrainList, DailyTrainQueryVO.class);
        PageVO<DailyTrainQueryVO> pageVO = new PageVO<>();
        pageVO.setList(lists);
        pageVO.setTotal(pageInfo.getTotal());

        return pageVO;
    }

    public void deleteDailyTrain(Long id) {
        dailyTrainMapper.deleteByPrimaryKey(id);
    }

    /**
     * 生成某日所有车次的数据信息
     * 包括车次，车站，车厢，座位
     * @param date
     */
    @Transactional
    public void GenerateDaily(Date date){
        /**
         * 查出所有的车次的信息
         */
        List<Train> trainList = trainService.selectAll();
        if(CollUtil.isEmpty(trainList)){
            LOG.info("没有车次基础数据，任务结束");
            return;
        }

        /**
         * 循环每个车次 然后做生成的动作
         */
        for (Train train : trainList) {
            //TODO: 后续数据库中关于daily车次的各种数据也需要添加外键操作 这样车次删除后同样也要删除对应的其他信息
            LOG.info("生成日期【{}】的车次【{}】信息开始", DateUtil.formatDate(date),train.getCode());
            /**
             * 生成每日车次的数据
             */
            GenerateDailyTrain(date,train);

            /**
             * 生成每日车次对应的车站数据
             */
            dailyTrainStationService.GenerateDailyTrainStation(train.getCode(), date);

            /**
             * 生成车站对应的车厢数据
             */
            dailyTrainCarriageService.GenerateDailyTrainCarriage(train.getCode(), date);

            /**
             * 生成每节车厢对应的座位数据
             */
            dailyTrainSeatService.GenerateDailyTrainSeat(train.getCode(), date);

            /**
             * 生成当日date对应的余票数据
             * 需要多一个列车type字段 用于计算票价对应的基数使用
             */
            dailyTrainTicketService.GenerateDailyTrainTicket(train.getType(), train.getCode(), date);

            LOG.info("生成日期【{}】的车次【{}】信息结束", DateUtil.formatDate(date),train.getCode());
        }
    }

    /**
     * 生成每日车次的数据
     * 将这个部分的生成的核心代码提取出来 解耦
     * @param date
     * @param train
     */
    @Transactional
    public void GenerateDailyTrain(Date date, Train train){
        LOG.info("生成日期【{}】的车次【{}】车次信息开始", DateUtil.formatDate(date),train.getCode());
        //删除现有的每日车次的数据 再重新去生成
        DailyTrainExample dailyTrainExample = new DailyTrainExample();
        dailyTrainExample.createCriteria()
                .andDateEqualTo(date)
                .andCodeEqualTo(train.getCode());
        dailyTrainMapper.deleteByExample(dailyTrainExample);

        /**
         * 生成该车次对应的每日车次数据
         */
        DailyTrain dailyTrain = BeanUtil.copyProperties(train, DailyTrain.class);
        dailyTrain.setId(SnowUtil.getSnowflakeNextId());
        DateTime time = DateTime.now();
        dailyTrain.setCreateTime(time);
        dailyTrain.setUpdateTime(time);
        dailyTrain.setDate(date);
        dailyTrainMapper.insert(dailyTrain);

        LOG.info("生成日期【{}】的车次【{}】车次信息结束", DateUtil.formatDate(date),train.getCode());
    }
}
